(define *kR:songs* (list))
(define *kR:current-song* "default")
(define *kR:in-song-load* #f)


;; Plugin Chains
;Gets alled when new Song was created
(define *kR:songs:events:add* '())
;Gets called the a song was loaded
(define *kR:songs:events:load* '())
;Gets called, when the current song was unloaded
(define *kR:songs:events:reset* '())


; Use this macro to define a song
; p.e.
; (song "Glorious"
;     (gbpiano "Piano" (midi-ch 0))
;     (instr "Bass" "NiKP " "-NI-" (midi-ch 1))
;
; Note: calling the song function twice with the same name
;       appends the song two times to the *kR:songs*
;       this is because maybe you want to play a song two times
;       in a set.

(define-macro (song name . body)
  ;deactivate all instruments (deactivate and not remove)
   ;will fotunately save loading times
   ;if you plan to use an instrument twice
   `(begin
    (song:reset-enviroment)
   ;set the song as actual song
   (set! *kR:current-song* ,name)
               
   ;call plugin chain
   ;(plugins:call *kR:songs:events:add* name)
               
   (append! *kR:songs* (list (cons ,name (lambda () ,@body))))))


(define (song:reset-enviroment)
   ;deactivate all instruments (deactivate and not remove)
   ;will fotunately save loading times
   ;if you plan to use an instrument twice
   (for-each (lambda(id)
                (instr:set id "active" #f)
                (instr:set id "bypass-midi" #f)
                ) (instr:ids) )
                            
   ;reset Keyboard bindings
   (keys:reset)
   ;(toggle:reset) ;existing toggles
   
   (key-up #\n (next-song))
   
   ;(plugins:call *kR:songs:events:reset*)
                            
   ;Update the graph (without instruments)
   (instr:update)
)

;load a song
(define (load-song name)
   (if (assoc name *kR:songs*)
       (begin
              (plugins:call ) 
                                                           
              (print "load song" name)
                                                           
              ;switch to song load
              (set! *kR:in-song-load* #t)
            
              ;prepare the enviroment
              (song:reset-enviroment)                

              ;load the song
              ((cdr (assoc name *kR:songs*))
              ;mark as current song
              (set! *kR:current-song* name))
                            
              ;call the plugin chain
              ;(plugins:call *kR:songs:events:load* name)
                            
              ;leave song load
              (set! *kR:in-song-load* #f)              
              )))

;get the position of the song in the Rack
; return #f if not found
(define song-position:temp #f)
(define (song-position name)
   (set! song-position:temp #f)
   (dotimes (i (length *kR:songs*))
      (if (string=? (car (list-ref *kR:songs* i)) name)
          (set! song-position:temp i)))
   song-position:temp)

;select the next song
(define (next-song)
   (load-song (car (list-ref *kR:songs* (min (- (length *kR:songs*) 1) (+ 1 (song-position *kR:current-song*)))))))